// 工具和配置
import Utils from '../utils/index';
import Dom from '../utils/Dom';
import Events from '../utils/Events';
import Http from '../utils/Http';
import Config from '../config';
import OperationParser from './OperationParser';

// 模块
import GanttTooltip from './GanttTooltip';
import GanttModal from './GanttModal';
import GanttContextMenu from './GanttContextMenu';
import GanttTimer from './GanttTimer';
import TimeRange from './TimeRange';
import GanttValidate from './GanttValidate';
import GanttCache from './GanttCache';
import Header from './GanttHeader';

// ui
import Loading from '../ui/loading';

// highcharts 相关
import Highcharts from 'highcharts/highstock';
import xRange from 'highcharts/modules/xrange';
import GanttPlugin from './GanttPlugin';
import Modal from '../ui/Modal';

xRange(Highcharts);

class Gantt {
    constructor(el, options) {

        this.root = Dom.get(el);
        this.header = new Header(this.root);

        this.el = Dom.append(this.root, 'div', 'container')

        this.options = Utils.extend({}, options);
        this.loading = new Loading();

        // 其他组件初始化
        GanttPlugin(Highcharts, this);
        this.modal = new GanttModal(this);
        this.contextmenu = new GanttContextMenu(this);
        this.tooltip = new GanttTooltip(this);
        this.timer = new GanttTimer(this);
        this.timeRange = new TimeRange(this);
        this.validate = new GanttValidate(this);
        this.cache = new GanttCache();


        // 记录有变动的 Operations，这些变动一般是拖动图块
        this.changedOperations = {};

        // 当前是否有滚动条
        this.hasScrollbar = false;

        // 拖动的模式，有单模式、组模式、浇次模式
        this.dragModel = 'single';

        this.init();

        // 订阅头部按钮点击事件
        Events.on('btnClick', (key, ...args) => {
            switch (key) {
                case 'save':
                    this.saveOperationData();
                    break;
                case 'goto':
                    this.modal.gotoModal(null, targetTime => {
                        this.goto(targetTime);
                        return true;
                    });
                    break;
                case 'resetTime':
                    this.resetTime();
                    break;
                case 'single':
                    this.dragModel = 'single';
                    break;
                case 'group':
                    this.dragModel = 'group';
                    break;
                case 'castGroup':
                    this.dragModel = 'castGroup';
                    break;
                case 'refresh':
                    this.refresh();
                    break;
                case 'logHeatMsg':
                    this.logHeatMsg();
                    break;
                case 'system':
                    this.modal.showMasterDataModal(args[0]);
                    break;
                case 'unscheduleCast':
                    this.unscheduleCast();
                    break;
                case 'staticSchedule':
                    this.staticSchedule();
                    break;
                case 'rePlan':
                    this.rePlan();
                    break;
                case 'planConfirm':
                    this.planConfirm();
                    break;
                default:
                    console.log(key);
                    break;
            }
        });

        // 主数据维护是更新通知，从 MasterDataModal 中触发的，目前只有设备数据会触发，所以只考虑设备数量和设备名称
        Events.on('masterDataUpdated', () => {
            this.timeRange.timeRange = null;
            if (this.chart) {
                this.chart.destroy();
                this.chart = null;
            }
            this.initChart(() => {
                this.alignCastPlan();
            });
        });


        Events.on('facilityRepairsUpdated', () => {
            this.chart.renderRepairs();
            this.doValidate();
        });

        Events.on('raodongAction',()=>{
            this.raodongAction()
        })

        window.onresize = () => {
            this.timer.addTimeout('windowResize', 100, () => {
                Events.emit(Config.eventKey.windowResize);
            });
        }
    }

    init() {
        this.cache.loadData(() => {
            this.chartContainer = Dom.append(this.el, 'div', 'chart-container');
            this.initCastPlan();
            this.initChart();
        });
    }

    /********************************* 甘特图相关操作 ***********************************************/
    initChart(callback) {

        let facilities = this.cache.getAll('facilities');

        if (!facilities || facilities.length === 0) {
            alert('设备数据为空，无法初始化系统！');
            return false;
        }

        this.facilitiesNoMap = {};
        this.facilities = facilities.sort((a, b) => { // 根据 facilityCode 进行排序
            return a.facilityCode.localeCompare(b.facilityCode);
        });
        // 工序 ID，用于计算 y 值
        this.facilitiesNoMap = Utils.calcLane(this.facilities);

        //计算所有设备文字长度，方便固定左侧 Y 轴的宽度
        // 因为无法通过字符长度计算宽度，所以下面是通过创建 svg text 并动态复制内容，然后计算宽度（ svg 的 getBBox API)
        // 最终用于 GanttPlugins.js
        let maxFacilitiesLabelWidth = 0,
            svgTextWidth = null,
            svgText = document.createElementNS("http://www.w3.org/2000/svg", "text");
        svgText.setAttributeNS(null, 'font-size', '12px');

        Highcharts.svgDefs.appendChild(svgText);
        this.facilities.forEach(f => {
            svgText.innerHTML = f.facilityDesc;
            svgTextWidth = svgText.getBBox().width;
            if (svgTextWidth > maxFacilitiesLabelWidth) {
                maxFacilitiesLabelWidth = svgTextWidth
            }
        });
        this.maxFacilitiesLabelWidth = Math.round(maxFacilitiesLabelWidth);


        //处理甘特图容器高度
        let desiredHeight = (this.facilities.length + 1) * 40,
            containerHeight = window.innerHeight - 70 - Dom.size(this.planContainer).h;
        this.yMax = null;
        if (containerHeight < desiredHeight) {
            this.yMax = Math.floor(containerHeight / 40) - 2;
            desiredHeight = containerHeight;
            this.hasScrollbar = true;
        } else { // 处理浇次池高度
            let height = document.body.clientHeight - desiredHeight - 70;
            this.planContainer.style.height = height + 'px';
        }
        this.chartContainer.style.height = desiredHeight + 'px';
        this.loadChartData(null, null, true, callback, true);
    }

    chartOnLoad(chart) {
        this.updateRealtimeData(chart);
        this.alignCastPlan(chart);
        this.loading.hide();

        //定时刷新数据及当前时间线
        this.timer.addInterval('readTimeLine', 3 * Utils.timeUnit.minutes, () => {
            this.updateRealtimeData();
        });
        chart.renderRepairs();

        // 定时刷新数据
        this.timer.refreshDataTimer();

        Dom.addEvent(chart.container, 'mousewheel', e => {
            if (this.hasScrollbar) {
                this.scrollY(e.deltaY);
                return Dom.nodefault(e);
            }
        });
    }

    /**
     * y 轴滚动操作
     * @param {boolean} zoomout 是否是放大操作（向上滚动）
     */
    scrollY(zoomout) {
        let yAxis = this.chart.yAxis[0],
            range = zoomout > 0 ? 1 : -1,
            min = yAxis.min + range,
            max = yAxis.max + range,
            dataMin = yAxis.dataMin,
            dataMax = yAxis.dataMax;
        if (min < dataMin || max > dataMax) {
            return false;
        }
        this.tooltip.hide();
        yAxis.setExtremes(min, max);
    }

    /**
     * 加载操作数据
     * @param {number | string | undefined} 开始时间
     * @param {number | string | undefined} 结束时间
     * @param {boolean} reset 是否需要更具操作数据更新炉次信息
     * @param {function | undefined} 操作完成后的回调函数
     * @param {boolean} resetData 是否先清空图表中的数据
     */
    loadChartData(start, end, reset, callback, resetData) {
        if (!start || !end) {
            let time = this.timeRange.calcTime();
            start = time[0];
            end = time[1];
        }

        if (typeof start !== 'string') {
            start = Utils.dateFormat(start, '-', true);
        }

        if (typeof end !== 'string') {
            end = Utils.dateFormat(end, '-', true);
        }


        Http.post(Config.api.operationData, JSON.stringify([{
            firstTime: start,
            lastTime: end
        }]), data => {
            this.cache.updateOperationsRute(data);
            this.parseOperationData(data, reset, series => {
                this.initOrUpdateChart(series, resetData, callback);
            })
        });
    }

    // 重置时间轴
    resetTime() {
        let timeRange = this.timeRange.resetTime(this.chart.plotLeft + this.chart.plotWidth / 2);
        if (timeRange) {
            this.loadChartData(timeRange[0], timeRange[1]);
        } else {
            this.chart.xAxis[0].setExtremes(this.timeRange.showRange[0], this.timeRange.showRange[0]);
        }
    }

    // 时间跳转
    goto(time) {
        let timeRange = this.timeRange.goto(time);
        if (timeRange) {
            this.loadChartData(timeRange[0], timeRange[1]);
        } else {
            this.initOrUpdateChart();
        }

    }

    // 刷新
    refresh() {
        // 1、情况当前图块修改数据及选中状态
        this.changedOperations = {};
        this.heatChangeSid = false;
        this.chart.selectedChange();
        Events.emit('statusChange', 'dataUpdate', false);
        // 2、根据当前的时间范围重新加载甘特图
        let timeRange = this.timeRange.refresh();
        this.showLoading();
        this.loadChartData(timeRange[0], timeRange[1], false, () => {
            this.initCastPlan();
            this.hideLoading();
            this.doValidate();
        }, true);
        // 3、动态预排提示
        Http.post(Config.api.findRaodong, null, res => {
            console.log(res)
            if (res && res.raodongReason) {
                this.confirmModal = new Modal('提示', res.raodongReason, isOK => {
                    if (isOK) {
                        this.confirmModal.show(true);
                        this.showLoading();
                        Http.post(Config.api.updateRaodong, JSON.stringify({
                            rdFlag: 1,
                        }), res => {
                            this.hideLoading()
                            alert('操作成功')
                        })
                    }
                })
            }
        });
        this.timer.resetRefreshDataTimer();
        this.header.renderIron();
    }

    // 重新排程
    rePlan() {
        let data = [];
        Http.post(Config.api.loadCastMsg, null, res => {
            for (let r of res) {
                data.push({sid:r.sid,castNo:r.castNo});
            }
            let template = `<table><thead><tr><th width="1px"></th><th>序号</th><th>浇次号</th><th>开浇时间</th></tr></thead>`;
            data.forEach(d => {
                template += '<tr><td><input width="1px" type="checkbox" name="oneCheck" value="'+d.sid+'"/></td><td>' + d.sid + '</td><td>' + d.castNo + '</td><td><input type="datetime-local" step="1"></td></tr>';
            });
            this.showRePlanModal(template + '</table>', '重新排程-选择浇次', 600);
        });
    }

    showRePlanModal(content, title, width = 460) {
		if (typeof content === 'string') {
			content = '<div class="confirm-modal">' + content + '</div>';
		}

		if (!this.confirmModal) {
			this.confirmModal = new Modal(title, content, isOK => {
			    if(isOK){
			        //确定
                    let modal = this.confirmModal;
                    let tBody = modal.modalBody.children[0].children[0].tBodies[0];
                    let res = [];
                    for (let i=0;i<tBody.childNodes.length;i++) {
                        if(tBody.childNodes[i].cells[0].lastChild.checked){
                            //勾选
                            let planCastTime = tBody.childNodes[i].cells[3].firstChild.value.replace('T',' ');
                            let msg = {sid:tBody.childNodes[i].cells[1].firstChild.data,castNo:tBody.childNodes[i].cells[2].firstChild.data,planCastTime:planCastTime};
                            res.push(msg);
                        }
                    }
                    Http.post(Config.api.reschedule, res, data => {
                        alert(data);
                    });
                }
				this.confirmModal.show(true);
			});

			// console.log(this.confirmModal);
            // let tBody = this.confirmModal.modalBody.children[0].children[0].tBodies[0];
            // debugger;
            // this.confirmModalClickEvent = Dom.addEvent(tBody, 'click', e => {
            //     let target = e.target;
            //     debugger
            //     return Dom.nodefault(e);
            // });

		} else {
			this.confirmModal.setContent(content);
			this.confirmModal.title.innerHTML = title;
			this.confirmModal.show();
		}
		this.confirmModal.modal.style.width = width + 'px';
	}


    // 排程确认
    planConfirm() {
        let data = [];
        Http.post(Config.api.loadCastMsg, null, res => {
            for (let r of res) {
                data.push({sid:r.sid,castNo:r.castNo});
            }
            let template = `<table><thead><tr><th width="1px"></th><th>序号</th><th>浇次号</th></tr></thead>`;
            data.forEach(d => {
                template += '<tr><td><input width="1px" type="checkbox" checked name="oneConfirmCheck" value="'+d.sid+'"/></td><td>' + d.sid + '</td><td>' + d.castNo + '</td></tr>';
            });
            this.showPlanConfirmModal(template + '</table>', '排程确认-选择浇次', 600);
        });
    }

    showPlanConfirmModal(content, title, width = 460) {
        if (typeof content === 'string') {
            content = '<div class="confirm-modal">' + content + '</div>';
        }
        if (!this.planConfirmModal) {
            this.planConfirmModal = new Modal(title, content, isOK => {
                if(isOK){
                    //确定
                    let modal = this.planConfirmModal;
                    let tBody = modal.modalBody.children[0].children[0].tBodies[0];
                    let res = [];
                    for (let i=0;i<tBody.childNodes.length;i++) {
                        if(tBody.childNodes[i].cells[0].lastChild.checked){
                            //勾选
                            let msg = {sid:tBody.childNodes[i].cells[1].firstChild.data,castNo:tBody.childNodes[i].cells[2].firstChild.data,isSelected:1};
                            res.push(msg);
                        }else{
                            //未勾选
                            let msg = {sid:tBody.childNodes[i].cells[1].firstChild.data,castNo:tBody.childNodes[i].cells[2].firstChild.data,isSelected:0};
                            res.push(msg);
                        }
                    }
                    this.showLoading();
                    Http.post(Config.api.confirm, res, data => {
                        this.hideLoading();
                        alert(data);
                    });
                }
                this.planConfirmModal.show(true);
            });
        } else {
            this.planConfirmModal.setContent(content);
            this.planConfirmModal.title.innerHTML = title;
            this.planConfirmModal.show();
        }
        this.planConfirmModal.modal.style.width = width + 'px';
    }

    // 手动快照
    logHeatMsg() {
        this.showLoading();
        let date = new Date(),
            seperator1 = '-', //格式分隔符
            year = date.getFullYear(), //获取完整的年份(4位)
            month = date.getMonth() + 1, //获取当前月份(0-11,0代表1月)
            strDate = date.getDate() // 获取当前日(1-31)
        if (month >= 1 && month <= 9) month = '0' + month // 如果月份是个位数，在前面补0
        if (strDate >= 0 && strDate <= 9) strDate = '0' + strDate // 如果日是个位数，在前面补0
        let currentdate = year + seperator1 + month + seperator1 + strDate;
        Http.post(Config.api.logHeatMsg, JSON.stringify({
            logDate: currentdate
        }), data => {
            alert('操作成功')
            this.hideLoading();
        });
    }

    // 拖动
    chartDrag(min, max) {
        min = Utils.timeRound(min, Utils.timeUnit.minutes);
        max = Utils.timeRound(max, Utils.timeUnit.minutes);
        this.timeRange.setShowRange(min, max, timeRange => {
            if (timeRange) {
                // console.log(Utils.dateFormat(timeRange[0], '-', true), Utils.dateFormat(timeRange[1], '-', true));
                this.loadChartData(timeRange[0], timeRange[1], true);
            } else {
                // console.log('timeRange is Empty');
            }
            this.validate.validate();
        });
    }

    // 显示 loading
    showLoading() {
        this.loading.loading.style['background-color'] = 'rgba(255, 255, 255, 0.3)';
        this.loading.show('处理中，请稍后...');
    }

    // 隐藏 loading
    hideLoading() {
        this.loading.hide();
    }

    /**
     * 解析操作数据
     * @param {List} data 操作数据
     * @param {boolean} reset 是否需要更新浇次数据
     * @param {function} callback 回调函数
     */
    parseOperationData(data, reset, callback) {
        if (data.length === 0) {
            callback([{
                id: 'empty',
                data: []
            }]);
            return false;
        }
        let result = OperationParser.parse(data, this.facilitiesNoMap, this.facilities),
            series = result.series,
            heatsId = result.heatsId,
            heat = null,
            doCallback = () => {
                series.forEach(s => {
                    heat = this.cache.getById('heats', s.heatSid);
                    s.caId = heat ? heat.caId : '';
                    s.taskCounter = heat ? heat.taskCounter : '';
                });
                callback(series);
            };
        if (reset) {
            this.cache.updateCastByHeats(heatsId, () => {
                doCallback();
            });
        } else {
            doCallback();
        }

    }

    /**
     * 初始化或更新图表
     * @param {Array} series 数据列配置
     * @param {boolean} reset 是否先清空数据
     * @param {function | undefined} callback 回调函数
     */
    initOrUpdateChart(series, reset, callback = Utils.noop) {
        let minTime = Infinity,
            maxTime = 0;
        if (!this.chart) {
            let _this = this,
                options = {
                    chart: {
                        type: 'xrange',
                        animation: false,
                        plotBorderWidth: 1,
                        plotBorderColor: '#7A7A7A',
                        backgroundColor: null,
                        spacing: 1,
                        reflow: false
                    },
                    title: {
                        text: null
                    },
                    xAxis: {
                        type: 'datetime',
                        dateTimeLabelFormats: {
                            week: '%m/%d',
                            day: '%m/%d'
                        },
                        min: this.timeRange.showRange[0],
                        max: this.timeRange.showRange[1],
                        lineWidth: 0,
                        tickLength: 8,
                        tickWidth: 1,
                        tickColor: '#7A7A7A',
                        opposite: true,
                        gridLineWidth: 1,
                        gridLineColor: '#CACAC6',
                        tickInterval: Utils.timeUnit.hours,
                        minorTickInterval: 15 * 60 * 1000,
                        minorTickLength: 4,
                        minorTickWidth: 1,
                        labels: {
                            padding: 0,
                            rotation: 0
                        },
                        minorGridLineColor: '#E8E8E9',
                        minorGridLineDashStyle: 'Dash',
                        events: {
                            afterSetExtremes: e => {
                                this.chartDrag(e.min, e.max);
                            }
                        }
                    },
                    yAxis: {
                        allowDecimals: false,
                        title: {
                            text: null
                        },
                        tickLength: 8,
                        tickWidth: 1,
                        tickColor: '#7A7A7A',
                        gridLineColor: '#CACAC6',
                        tickPixelInterval: 60,
                        minorTickInterval: 0.5,
                        minorGridLineWidth: 1,
                        minorGridLineColor: '#E8E8E9',
                        minorGridLineDashStyle: 'Dash',
                        max: this.facilities.length,
                        endOnTick: true,
                        showEmpty: true,
                        tickInterval: 1,
                        labels: {
                            y: 35,
                            formatter: function () {
                                if (this.value.toString().indexOf('.') === -1 && this.value < _this.facilities.length) {
                                    return _this.facilities[this.value].facilityDesc;
                                }
                                return null;
                            }
                        },
                        // 背景颜色须更具条件填充
                        plotBands: Utils.calcPlotbands(),
                        reversed: true
                    },
                    tooltip: {
                        enabled: false
                    },
                    legend: {
                        enabled: false
                    },
                    credits: {
                        enabled: false
                    },
                    plotOptions: {
                        series: {
                            grouping: false,
                            animation: false,
                            pointWidth: 16,
                            colorByPoint: false,
                            borderRadius: 0,
                            pointPadding: 0,
                            groupPadding: 0,
                            pointPlacement: 0,
                            borderColor: '#000',
                            cursor: 'pointer',
                            point: {
                                cursor: 'pointer',
                                events: {
                                    mouseOver: function (e) {
                                        if (this.series.chart.currentSelectPoint &&
                                            this.series.chart.currentSelectPoint.extra &&
                                            this.series.chart.currentSelectPoint.extra.sid === this.extra.sid) {
                                            return false;
                                        }
                                        _this.mouseOver = true;
                                        let point = this;
                                        setTimeout(() => {
                                            if (_this.mouseOver && point.graphic.element.className.baseVal.indexOf('highcharts-point-current') === -1) {

                                                _this.tooltip.show('detail', point);
                                            }
                                        }, 500);
                                    },
                                    mouseOut: function () {
                                        _this.mouseOver = false;
                                        _this.tooltip.hide('detail');
                                    }
                                }
                            }
                        }
                    },
                    series: series
                };
            if (this.yMax != null) {
                options.yAxis.min = 0;
                options.yAxis.max = this.yMax;
                options.yAxis.scrollbar = {
                    enabled: true,
                    margin: -20,
                    showFull: true,
                    zIndex: 5
                }
            }

            this.chart = Highcharts.chart(this.chartContainer, options, c => {
                this.chartOnLoad(c);
            });
            series.forEach(s => {
                if (s.id !== 'empty') {
                    if (s.extra.min < minTime) {
                        minTime = s.extra.min;
                    }
                    if (s.extra.max > maxTime) {
                        maxTime = s.extra.max
                    }
                }
            });
            this.timeRange.fixedRange(minTime, maxTime);
            this.validate.validate();

        } else {
            if (reset) { // 先清空数据列
                while (this.chart.series.length) {
                    this.chart.series[this.chart.series.length - 1].remove(false);
                }
            }

            if (series && series.length > 0) {
                series.forEach(s => {
                    if (s.id !== 'empty') {
                        if (s.extra.min < minTime) {
                            minTime = s.extra.min;
                        }
                        if (s.extra.max > maxTime) {
                            maxTime = s.extra.max
                        }
                    }

                    if (!this.chart.get(s.id)) {
                        this.chart.addSeries(s, false);
                    }
                });
            }

            this.timeRange.fixedRange(minTime, maxTime);

            this.chart.xAxis[0].setExtremes(this.timeRange.showRange[0], this.timeRange.showRange[1]);
            callback();
        }
    }

    // 更新当前时间刻度线
    updateRealtimeData(chart) {
        if (!chart) {
            chart = this.chart;
        }
        // 更新数据
        chart.xAxis[0].removePlotLine('time-line');
        chart.xAxis[0].addPlotLine({
            value: new Date().getTime(),
            width: 2,
            id: 'time-line',
            color: 'red',
            zIndex: 4
        });
    }

    /********************************* 甘特图相关操作 end ***********************************************/


    /********************************* 浇次计划相关内容 **************************************************/
    // 初始话浇次迟
    initCastPlan() {
        if (!this.planContainer) {
            this.planContainer = Dom.append(this.el, 'div', 'plan-container');
        } else {
            this.planContainer.innerHTML = '';
        }

        Http.get(Config.api.castData, null, data => {
            this.cache.updateCastHeat(data);
            this.renderCastPlan(data);
        })
    }

    // 更具浇次数据渲染浇次池
    renderCastPlan(casts) {
        casts.forEach((c, index) => {
            c.root = Dom.append(this.planContainer, 'div', 'plan', '<p>' + c.cast.castNo + '</p>');
            if (c.cast.castNo.substring(0, 1) === 'E') {
                c.container = Dom.append(c.root, 'ul', '');
            } else if (c.cast.castNo.substring(0, 1) === 'F') {
                c.container = Dom.append(c.root, 'ul', 'color2');
            } else if (c.cast.castNo.substring(0, 1) === 'G') {
                c.container = Dom.append(c.root, 'ul', 'color3');
            } else {
                c.container = Dom.append(c.root, 'ul', '');
            }
            //c.container = Dom.append(c.root, 'ul', (index + 1) % 2 === 0 ? 'color2' : '');
            c.container.sid = c.cast.sid;

            let liStr = '<li class="start"></li>';

            c.heats.forEach((h, index) => {
                if (index > 0) {
                    let zzjhh = h.precRollPlanNo;
                    let qzzjhh = c.heats[index - 1].precRollPlanNo;
                    if (zzjhh && qzzjhh && zzjhh !== qzzjhh) {
                        liStr += '<li style="float:right;margin-top:-5px;margin-left:-1px;width:0px;height: 13px;background-color: red; border-right: 2px solid red;"></li>';
                    }
                }
                liStr += '<li class="item ' + (h.heatStat === 'R' ? 'wait' : 'finish') + '" data-sid="' + h.sid + '" data-status="' + h.heatStat + '"></li>';
            });
            c.container.innerHTML = liStr;
        });

        if (!this.planInited) {

            Dom.addEvent(this.planContainer, 'contextmenu', e => {
                this.tooltip.hide('heat');
                if (e.target.tagName === 'LI') {
                    if (e.target.className.indexOf('start') !== -1) {
                        return Dom.nodefault(e);
                    }

                    let castSid = e.target.parentNode.sid,
                        heatStat = e.target.getAttribute('data-status'),
                        heatSid = parseInt(e.target.getAttribute('data-sid'));

                    this.contextmenu.showCastPlanContextmenu(castSid, heatSid, heatStat, e);
                }
                return Dom.nodefault(e);
            });

            Dom.addEvent(this.planContainer, 'mousemove', e => {
                if (e.target.tagName === 'LI') {
                    if (e.target.className.indexOf('start') !== -1) {
                        return Dom.nodefault(e);
                    }
                    this.timer.addTimeout('showHeatTooltip', 100, () => {
                        this.tooltip.showCastHeat(parseInt(e.target.getAttribute('data-sid')), e);
                    });
                }
            });

            Dom.addEvent(this.planContainer, 'mouseout', e => {
                this.timer.addTimeout('hideHeatTooltip', 100, () => {
                    this.timer.clearTimeout('showHeatTooltip');
                    this.tooltip.hide('heat');
                })
            });

            this.planInited = true;
        }
    }

    /**
     * 将浇次计划 div 与图表的 y 轴对其
     */
    alignCastPlan(chart) {
        if (!chart) {
            chart = this.chart;
        }
        let left = chart.yAxis[0].left - 1;
        this.planContainer.style['margin-left'] = left + 'px';
        this.planContainer.style.width = 'calc(100% - ' + left + 'px)';
    }

    // 更新浇次计划炉次状态
    updateCastPlan() {
        let status = null,
            heatObj = null;
        this.planContainer.childNodes.forEach(plan => {
            plan.childNodes[1].childNodes.forEach(heat => {
                status = heat.getAttribute('data-status');
                if (status) {
                    heatObj = this.cache.getById('heats', parseInt(heat.getAttribute('data-sid')));
                    if (heatObj && heatObj.heatStat !== status) {
                        heat.className = 'item ' + (heatObj.heatStat === 'R' ? 'wait' : 'finish');
                        heat.setAttribute('data-status', heatObj.heatStat);
                    }
                }
            });
        });
    }

    /********************************* 浇次计划相关内容  end **************************************************/


    /***************************** 图块右键菜单相关方法 start ********************************************************/
    // 这些方法的名称要和 GanttPlugins 中右键菜单定义的 code 一致

    // 下 PDI
    releasePdi(heatSid, point) {
        // if (point.extra.facilityNo.startsWith('BOF')) { // 转炉工序
        // 	// 加载 heat 数据
        // 	this.masterData.getById('heats', heatSid, heat => {
        // 		// 加载 GeNo
        // 		Http.get(Config.api.getValidWithGeNo, {
        // 			facilityNo: point.extra.facilityNo,
        // 			caId: heat.caId
        // 		}, data => {

        // 			// 根据 operationTimeConfigs 表里的数据组装 geNo 数组
        // 			let geNo = data.geNo,
        // 				matches = data.matches.map(m => {
        // 					return [m.bofL2TaskCounter, m.status, m.sid]
        // 				}),
        // 				name = point.series.name.split('_'),
        // 				routeIdSubfix = null;
        // 			if (name.includes('CAS')) {
        // 				routeIdSubfix = 'BA';
        // 			} else if (name.includes('LF')) {
        // 				routeIdSubfix = 'BF';
        // 			} else if (name.includes('RH')) {
        // 				routeIdSubfix = 'BR';
        // 			}

        // 			this.masterData.getByIndex('operationTimeConfigs', 'caId', heat.caId, operationTimes => {
        // 				let routeIdMap = {},
        // 					geNos = [],
        // 					temp = null;

        // 				operationTimes.forEach(d => {
        // 					if (!routeIdMap[d.routeId]) {
        // 						temp = d.routeId.split('_');
        // 						if (temp.includes('CAS')) {
        // 							geNos.push('BA' + geNo);
        // 						} else if (temp.includes('LF')) {
        // 							geNos.push('BF' + geNo);
        // 						} else if (temp.includes('RH')) {
        // 							geNos.push('BR' + geNo);
        // 						}
        // 						routeIdMap[d.routeId] = true;
        // 					}
        // 				});

        // 				geNos.push('BRP' + geNo.substring(1));

        // 				this.modal.showPdiModal({
        // 					sid: point.extra.sid,
        // 					geNo: geNos,
        // 					routeIdSubfix: routeIdSubfix,
        // 					matches: matches
        // 				}, result => {
        // 					this.finishedPdi(point, result);
        // 				});
        // 			});
        // 		});
        // 	});

        // } else { // 非转炉工序

        let facilityNo = point.extra.facilityNo;
        let heatSidTemp = point.extra.heatSid;

        if (facilityNo == 'CCM7') {
            Http.get(Config.api.mccrCheckOutHeatId, {
                heatSid: heatSidTemp
            }, data => {
                if (data) {
                    this.confirmModal = new Modal('操作提示', '此炉次还未绑定真实炉次号，确定下MCCR铸机PDI吗？', isOK => {
                        if (isOK) {
                            this.showLoading();
                            Http.get(Config.api.downPdi, {
                                sid: point.extra.sid
                            }, data => {
                                this.finishedPdi(point, data[0]);
                                this.confirmModal.show(true);
                            });
                        }
                    });
                } else {
                    this.showLoading();
                    Http.get(Config.api.downPdi, {
                        sid: point.extra.sid
                    }, data => {
                        this.finishedPdi(point, data[0]);
                    });
                }
            });
        } else {
            this.showLoading();
            Http.get(Config.api.downPdi, {
                sid: point.extra.sid
            }, data => {
                this.finishedPdi(point, data[0]);
            });
        }

        // }
    }

    // PDI 下达完成处理
    finishedPdi(point, data) {
        let extraData = point.extra;
        extraData.facilityNo = data.facilityNo;
        extraData.operationSeq = data.operationSeq;
        extraData.operationStat = data.operationStat;
        extraData.sid = data.sid;
        extraData.routeSid = data.routeSid;
        extraData.heatSid = data.heatSid;
        let newData = {
            extra: extraData
        };
        point.update(newData);
        this.hideLoading();
        this.cache.updateCastByHeats([data.heatSid]);
    }

    /**
     * 调度炉次
     * @param {Object} heat 炉次信息
     * @param {boolean} isDefaultRoute 是否是默认工艺路径
     */
    scheduleHeat(castSid, heatSid, isDefaultRoute) {
        let castHeat = this.cache.getCastHeatByHeatSid(heatSid),
            isFirst = castHeat.cast.castStat === 'R',
            heat = castHeat.heat,
            operationTimes = this.cache.getByIndex('operationTimeConfigs', 'caId', heat.caId),
            facilityCcm = '',
            castNo = this.cache.getById('casts', castSid).castNo,
            routeIdMap = {},
            routes = [];

        if (castNo.substring(0, 1) === 'E') {
            facilityCcm = 'CCM5';
        } else if (castNo.substring(0, 1) === 'F') {
            facilityCcm = 'CCM6';
        } else if (castNo.substring(0, 1) === 'G') {
            facilityCcm = 'CCM7';
        }
        operationTimes.forEach(d => {
            if (!routeIdMap[d.routeId]) {
                routes.push(d.routeId);
                routeIdMap[d.routeId] = true;
            }
        });

        this.modal.showCastModal({
            isFirst: isFirst,
            routes: routes,
            sid: heat.sid,
            facilityCcm: facilityCcm,
            isDefaultRoute: isDefaultRoute
        }, result => {
            this.finishedScheduleHeat(result);
        }, this.facilities);
    }

    /**
     * 完成炉次调度
     * 更新缓存数据
     * 更新浇次计划状态
     */
    finishedScheduleHeat(data) {
        this.parseOperationData([data[0].operationData], false, series => {
            series.forEach(s => {
                this.chart.addSeries(s, false);
            });
            this.chart.redraw();
            this.cache.update('casts', data[0].cast, false);
            this.cache.update('heats', data[0].heat, false);
            this.cache.updateOperationsRute(data[0].operationData);

            this.doValidate();
            this.updateCastPlan();
            this.alignCastPlan();
            this.hideLoading();
        });
    }

    // 显示浇次信息
    showCastInfo(heatSid) {
        let heat = this.cache.getById('heats', heatSid);
        Http.post(Config.api.getCastData, JSON.stringify([heat.castSid]), data => {
            this.modal.showCastInfo(data[0]);
        });
    }

    // 显示炉次信息
    showHeatInfo(heatSid) {
        Http.get(Config.api.getHeatData, {
            sid: heatSid
        }, data => {
            this.modal.showHeatInfo(data);
        });
    }

    //
    showSlabInfo(heatSid) {
        Http.get(Config.api.getSlabData, {
            sid: heatSid
        }, data => {
            this.modal.showSlabInfo(data);
        });
    }

    /**
     * 插入作业
     * @param {Highcharts.Point} point 数据点对象
     * @param {boolean} isBefore 是否是之前插入
     */
    insertOperation(heatSid, point, isBefore) {
        this.insertOperationParams = {
            routeSid: point.series.options.id,
            operation: {
                facilityNo: point.extra.facilityNo,
                routeSid: point.series.options.id,
                heatSid: point.series.options.heatSid,
                operationStat: 'S',
                operationSeq: point.extra.operationSeq + (isBefore ? 0 : 1)
            }
        };
        this.insertOperationPoint = point;
        this.modal.showInsertOperationModal(data => {
            this.insertOperationParams.operation.facilityNo = data.facilityNo;
            this.insertOperationParams.operation.planStartTime = data.planStartTime;
            this.insertOperationParams.operation.planEndTime = data.planEndTime;
            this.showLoading();
            Http.post(Config.api.insertOperation, JSON.stringify(this.insertOperationParams), result => {
                // 1.更新图表数据
                let series = OperationParser.parseSingle(result);
                this.insertOperationPoint.series.update(series);
                // 2.更新缓存数据
                this.cache.updateOperationsRute(result);
                // 3. 取消点选中状态
                this.chart.selectedChange();

                this.hideLoading();
                this.doValidate();
            });
        }, this.facilities);
    }

    // 删除作业
    deleteOperation(heatSid, point) {
        if (point.extra.operationStat !== 'S' || point.extra.facilityNo.startsWith('CCM') || point.extra.facilityNo.startsWith('SCM')) {
            alert('不允许删除作业');
            return false;
        }

        window.jsconfirm('是否删除作业？', result => {
            if (!result) {
                return false;
            }
            this.showLoading();
            Http.get(Config.api.deleteOperation, {
                routeSid: point.series.options.id,
                operationSeq: point.extra.operationSeq
            }, result => {
                let series = OperationParser.parseSingle(result);
                point.series.update(series);
                // 2.更新缓存数据
                this.cache.updateOperationsRute(result);
                // 3. 取消点选中状态
                this.chart.selectedChange();
                this.hideLoading();
                this.doValidate();
            });
        })
    }

    // 修改作业时间
    changeOperationTime(heatSid, point) {
        this.changedOperationTimePoint = point;
        if ((point.extra.operationStat === 'S' || point.extra.operationStat === 'I') && !point.extra.actualStartTime) {
            if (this.dragModel === 'single') {
                this.modal.changeHeatOperationTime((startTime, endTime) => {
                    let postData = this.calcChangeOperations(this.changedOperationTimePoint, startTime, endTime);
                    this.saveOperationData([postData], result => {
                        // 更新缓存
                        this.cache.updateOperationsRute(result);
                        // 更新图表状态
                        this.parseOperationData(result, false, series => {
                            series.forEach(s => {
                                this.chart.get(s.id).update(s, false);
                            });
                            this.chart.redraw();
                            this.chart.selectedChange();
                            this.hideLoading();
                        });
                    });
                }, point.extra.planStartTime, point.extra.planEndTime);
            } else {
                this.modal.showOperationModal(startTime => {
                    let postData = this.calcChangeOperations(this.changedOperationTimePoint, startTime);
                    this.saveOperationData([postData], result => {
                        // 更新缓存
                        this.cache.updateOperationsRute(result);
                        // 更新图表状态
                        this.parseOperationData(result, false, series => {
                            series.forEach(s => {
                                this.chart.get(s.id).update(s, false);
                            });
                            this.chart.redraw();
                            this.chart.selectedChange();
                            this.hideLoading();
                        });
                    });
                }, point.extra.planStartTime);
            }
        } else {
            alert('不允许修改作业时间');
        }
    }


    // 取消 PDI
    cancelPdi(heatSid, point) {
        let heat = this.cache.getById('heats', heatSid);

        if (point.extra.operationStat !== 'I') {
            alert('不能取消PDI');
            return false;
        }

        // if (heat.heatStat !== 'I') {
        // 	alert('不能取消 PDI');
        // 	return false;
        // }
        this.showLoading();
        Http.get(Config.api.canclePdi, {
            sid: point.extra.sid
        }, result => {
            if (result && result.length === 1) {
                let extraData = point.extra;
                extraData.operationStat = result[0].operationStat;
                // 更新图表数据
                point.update({
                    extra: extraData
                });
                // 更新缓存
                this.cache.update('operations', result[0]);
                if (result[0].facilityNo.startsWith('BOF')) {
                    this.cache.update('heats', {
                        sid: result[0].heatSid,
                        sgrp: 'N',
                        heatStat: 'S'
                    }, true);
                }
                this.hideLoading();
            }
        });
    }

    // 修改工艺路径
    changeRoute(heatSid, point) {
        let heat = this.cache.getById('heats', heatSid),
            operationTimes = this.cache.getByIndex('operationTimeConfigs', 'caId', heat.caId),
            routeIdMap = {},
            routes = [],
            temp = null,
            filteredRoutes = [],
            currentRouteLength = null;

        operationTimes.forEach(d => {
            if (!routeIdMap[d.routeId]) {
                routes.push(d.routeId);
                routeIdMap[d.routeId] = true;
            }
        });

        if (routes.length > 0) {
            currentRouteLength = point.series.name.split('_').length;

            routes.forEach(r => {
                if (r !== point.series.name) {
                    temp = r.split('_');
                    if (temp.length === currentRouteLength) {
                        filteredRoutes.push(temp.join(' -> '));
                    }
                }
            });

            if (filteredRoutes.length > 0) {
                this.modal.simpleSingleSelectModal('请选择工艺路径', filteredRoutes, (selectRute, modal) => {
                    this.showLoading();
                    Http.get(Config.api.changeRoute, {
                        routeSid: point.series.options.id,
                        routeId: selectRute.split(' -> ').join('_')
                    }, result => {
                        this.parseOperationData([result], false, series => {
                            this.chart.get(series[0].id).update(series[0]);
                        });
                        this.cache.updateOperationsRute([result]);
                        modal.show(true);
                        this.hideLoading();
                    });
                }, {
                    label: '工艺路径选择'
                });
                return true;
            }
        }
        alert('没有可选的工艺路径');
    }


    // 设置堆冷信息
    changeHotFlag(heatSid) {
        let heat = this.cache.getById('heats', heatSid);

        this.modal.showHeatHotFlagModal({
            sid: heat.sid
        }, result => {
            if (result.success == false) {
                this.hideLoading();
                alert(result.message);
            } else {
                this.refresh();
                this.hideLoading();
                alert('操作成功');
            }
        });
    }


    // 取消浇次调度
    unscheduleCast() {
        if (!this.chart.currentSelectPoint) {
            return false;
        }
        let heatSids = [],
            heats = this.cache.getHeatsByHeatSid(this.chart.currentSelectPoint.extra.heatSid);

        if (heats && heats.length > 0) {
            heats.forEach(h => {
                if (h.heatStat === 'S') {
                    heatSids.push(h.sid);
                }
            });

            if (heatSids.length > 0) {
                this.unscheduleHeat(heatSids, true);
            }
        }
    }

    // 静态算法调度
    staticSchedule() {
        this.modal.showStaticScheduleModal(this.cache.getAll('casts'), Utils.facilities, data => {
            // TODO: 数据接口处理
            console.log(data);
        });
    }

    // 回炉
    recycleHeat(heatSid, point) {
        let heat = this.cache.getById('heats', heatSid);
        if (heat === 'R') {
            alert('不能进行回炉！');
            return false;
        }

        this.showLoading();
        Http.get(Config.api.recycleHeat, {
            heatSid: heatSid
        }, result => {
            let series = null,
                heats = [],
                casts = [],
                operationRutes = [];

            result.forEach(r => {
                heats.push(r.heat);
                if (r.cast) {
                    casts.push(r.cast);
                }
                operationRutes.push(r.operationData.operationRoute.sid);
            });

            this.cache.clearMasterSlaveData('operationRoute', 'operations', operationRutes, {
                masterObjKey: 'operationRoute',
                masterObjIndex: 'routeSid'
            });

            if (casts.length > 0) {
                this.cache.updateAll('casts', casts, false);
            }
            // 更新炉次缓存
            this.cache.updateAll('heats', heats, false);
            this.updateCastPlan();


            series = point ? point.series : this.chart.searchSeriesByHeatSid(heatSid);
            if (!series) {
                return false;
            }

            series.remove();
            this.chart.currentSelectPoint = null;
            this.chart.selectedChange();
            this.hideLoading();
        });
    }

    // 取消调度
    unscheduleHeat(heatSids, seachPointSeries) {
        if (typeof heatSids !== 'object') {
            heatSids = [heatSids];
        }

        let series = null,
            heats = [],
            casts = [],
            operationRutes = [];

        this.showLoading();
        Http.post(Config.api.unschedule, JSON.stringify(heatSids), result => {
            // 删除数据列

            if (seachPointSeries || !this.chart.currentSelectPoint) {
                series = this.chart.searchSeriesByHeatSid(heatSids);
            } else {
                series = [this.chart.currentSelectPoint.series]
            }

            let needEmptySeries = false;
            if (!series) {
                return false;
            } else {
                needEmptySeries = series.length === this.chart.series.length;
            }

            // 更新图表
            series.forEach(s => {
                s.remove(false);
            })
            if (needEmptySeries) {
                this.chart.addSeries({
                    id: 'empty',
                    data: []
                }, false);
            }
            this.chart.redraw();
            // this.tooltip.hide();
            this.chart.currentSelectPoint = null;
            this.chart.selectedChange();


            console.log(result);
            // 更新缓存
            result.forEach(r => {
                heats.push(r.heat);
                if (r.cast) {
                    casts.push(r.cast);
                }
                operationRutes.push(r.operationData.operationRoute.sid);
            });


            this.cache.clearMasterSlaveData('operationRoute', 'operations', operationRutes, {
                masterObjKey: 'operationRoute',
                masterObjIndex: 'routeSid'
            });

            if (casts.length > 0) {
                this.cache.updateAll('casts', casts);
            }
            // 更新炉次缓存
            this.cache.updateAll('heats', heats);
            this.updateCastPlan();
            this.doValidate();
            this.hideLoading();
        });
    }

    // 合并浇次
    mergeCast(heatSid, point) {

        Http.get(Config.api.findCasts, null, casts => {
            let heatCast = this.cache.getCastHeatByHeatSid(heatSid);
            if (heatCast.cast.castStat !== 'R') {
                alert('不能合并该浇次');
                return false;
            }

            this.modal.singleSelectModal(casts, 'castNo', heatCast.cast.castNo, selectedCast => {
                this.showLoading();
                Http.get(Config.api.mergeCast, {
                    castSid1: heatCast.cast.sid,
                    castSid2: selectedCast
                }, result => {
                    this.cache.updateCastHeat(result);
                    this.hideLoading();
                });
                return true;
            }, {
                title: '请选择与浇次 ' + heatCast.cast.castNo + ' 合并的浇次',
                label: '浇次选择'
            });
        });
    }

    // 炉次更换浇次
    heatChangeCast(heatSid, point) {
        Http.get(Config.api.findCasts, null, casts => {
            let heatCast = this.cache.getCastHeatByHeatSid(heatSid);
            this.modal.singleSelectModal(casts, 'castNo', heatCast.cast.castNo, selectedCast => {
                this.showLoading();
                Http.get(Config.api.heatChangeCast, {
                    heatSid: heatCast.heat.sid,
                    castSid: selectedCast
                }, result => {
                    this.cache.updateCastHeat(result);
                    this.initCastPlan();
                    this.hideLoading();
                    this.doValidate(true);
                });
                return true;
            }, {
                title: '请选择浇次',
                label: '浇次选择'
            })
        });
    }

    // 炉次信息互换
    heatMessageChange(heatSid, point) {
        let heat = this.cache.getById('heats', heatSid);
        Http.get(Config.api.getHeats, {
            sid: heat.castSid
        }, heats => {
            this.modal.singleSelectModal(heats, 'taskCounter', heat.taskCounter, selectHeat => {
                this.showLoading();
                Http.get(Config.api.heatMessageChange, {
                    heatSid1: heat.sid,
                    heatSid2: selectHeat
                }, result => {
                    this.cache.updateCastHeat(result);
                    this.hideLoading();
                });
                return true;
            }, {
                title: '请选择炉次',
                label: '炉次选择'
            });
        });
    }

    // 炉次交换
    heatChange(heatSid, point) {
        if (!this.canHeatChange(point)) {
            return false;
        }
        let heat = this.cache.getById('heats', point.extra.heatSid);
        this.heat = heat;
        this.heatChangeSid = heat.sid;
        this.modal.showHeatChangeModal(heat.taskCounter, isOK => {
            if (isOK) {
                this.showLoading();
                Http.get(Config.api.heatChange, {
                    heatSid1: this.heat.sid,
                    heatSid2: this.heatChangeNewSid
                }, result => {
                    this.cache.updateCastHeat(result);
                    this.refresh();
                });
            }
            this.heatChangeSid = false;
        });
    }

    // 判断图块是否可以进行炉次交换
    canHeatChange(point) {
        point.series.points.forEach(p => {
            if (p.extra.facilityNo.startsWith('CCM')) { // 判断选中的图块所在炉次在铸机工序的图块的状态
                if (p.operationStat !== 'S') { //只有状态是S的才显示对话框
                    return false;
                }
            }
        });
        return true;
    }

    // 炉次顺序互换
    orderchange(heatSid, point) {
        let heat = this.cache.getById('heats', heatSid);
        Http.get(Config.api.getHeats, {
            sid: heat.castSid
        }, heats => {
            this.modal.singleSelectModal(heats, 'taskCounter', heat.taskCounter, selectHeat => {
                this.showLoading();
                Http.get(Config.api.orderchange, {
                    heatSid1: heat.sid,
                    heatSid2: selectHeat
                }, result => {
                    console.log(result);
                    // TODO: 确认是否有 castHeat 数据
                    if (result && result.operationDatas) {
                        let needRedraw = false;
                        result.operationDatas.forEach(operationDatas => {
                            if (operationDatas.operationRoute && operationDatas.operations) {
                                this.cache.update('operationRoute', operationDatas.operationRoute);
                                let series = this.chart.get(operationDatas.operationRoute.sid),
                                    points = {};

                                operationDatas.operations.forEach(operation => {
                                    this.cache.update('operations', operation);
                                    points[operation.sid] = operation;
                                });

                                if (series) {
                                    // series.update(OperationParser.parseRoute(operationDatas.operationRoute), false);
                                    series.points.forEach(p => {
                                        if (points[p.extra.sid]) {
                                            p.update(OperationParser.parseOperation(points[p.extra.sid]), false);
                                        }
                                    });
                                    needRedraw = true;

                                }
                            }
                        });

                        if (needRedraw) {
                            this.chart.redraw();
                        }
                    }
                    this.hideLoading();
                    this.doValidate();
                });
                return true;
            }, {
                title: '炉次选择',
                label: '选择炉次'
            });
        });
    }

    // 设置炉次完成或设置炉次吊销
    heatCompleteOrClose(heatSid, isClose) {
        let heat = this.cache.getById('heats', heatSid);
        if (!isClose) {
            if (heat.heatStat === 'R' || heat.heatStat === 'F') {
                alert('不能设置炉次完成');
                return false;
            }
        } else {
            if (heat.heatStat !== 'R') {
                alert('不能设置吊销炉次');
                return false;
            }
        }

        this.showLoading();
        Http.get(Config.api[isClose ? 'heatClose' : 'heatComplete'], {
            heatSid: heat.sid
        }, operations => {
            this.finishedHeatCompleteOrClose(operations, isClose, heatSid);
        });
    }

    //跳转文档系统
    openWord(heatSid) {
        let heat = this.cache.getById('heats', heatSid);
        Http.get(Config.api['getWordUrlApi'], {
            heatSid: heat.sid
        }, operations => {
            window.open(operations);
        });
    }

    // 完成设置炉次完成或设置炉次吊销
    finishedHeatCompleteOrClose(operations, isClose, heatSid) {
        let i = 0,
            total = operations.length,
            heatSids = [];

        if (total === 0) {
            if (isClose) {
                this.refresh();
            }
        } else {


            // 1、对 operation 数据进行更新操作
            for (; i < total; i++) {
                heatSids.push(operations[i].heatSid);
                this.cache.update('operations', operations[i]);
            }
debugger
            // 2、更新浇次、炉次数据
            Http.post(Config.api.castDataByheats, JSON.stringify(heatSids), result => {
                this.cache.updateCastHeat(result);
                if (isClose) {
                    this.refresh();
                } else {
                    let series = this.chart.searchSeriesByHeatSid(heatSid),
                        data = [],
                        d = null;
                    if (series) {
                        operations.forEach(o => {
                            d = OperationParser.parseOperation(o);
                            if (d) {
                                data.push(d);
                            }
                        });

                        series.update({
                            data: data
                        });
                        series.points.forEach(p => {
                            p.graphic.addClass(p.getClassName(), true);
                        })
                        this.chart.selectedChange();
                    }
                    this.updateCastPlan();
                    this.hideLoading();
                }
            });
        }
    }

    // 显示炉次，即图中选中炉次
    showHeat(heatSid) {

        let min = null,
            max = null,
            centerTime = null,
            timeRange = null,
            series = null,
            doShowHeat = (operationRoute) => {
                min = new Date(operationRoute.planStartTime).getTime();
                max = new Date(operationRoute.planEndTime).getTime();
                centerTime = Utils.timeRound(min + (max - min) / 2, Utils.timeUnit.minutes, true);
                timeRange = this.timeRange.goto(centerTime);
                if (timeRange) {
                    this.loadChartData(timeRange[0], timeRange[1], false, () => {
                        series = this.chart.searchSeriesByHeatSid(heatSid);
                        if (!series) {
                            return false;
                        }
                        this.chart.selectSeriesByPoint(series.points[0]);
                    });
                } else {
                    this.chart.xAxis[0].setExtremes(this.timeRange.showRange[0], this.timeRange.showRange[1]);
                    series = this.chart.searchSeriesByHeatSid(heatSid);
                    if (!series) {
                        return false;
                    }
                    this.chart.selectSeriesByPoint(series.points[0]);
                }
            }
        let operationRoute = this.cache.getByIndex('operationRoute', 'heatSid', heatSid);
        if (operationRoute && operationRoute.length) {
            doShowHeat(operationRoute[0]);
        } else {
            Http.get(Config.api.operationRouteByHeat, {
                sid: heatSid
            }, result => {
                if (result && result.length) {
                    doShowHeat(result[0].operationRoute);
                    this.cache.updateOperationsRute(result);
                }
            })
        }
    }

    /***************************** 图块右键菜单相关方法 end ********************************************************/

    calcChangeOperations(point, startTime, endTime) {
        let result = {
                operationRoute: OperationParser.toRoute(point.series)
            },
            startTimeStamp = new Date(startTime).getTime();


        if (this.dragModel === 'single' || this.dragModel === 'castGroup') { // 浇次模式按照单模式走
            result.operations = [OperationParser.toOperation(point)]
            result.operations[0].planStartTime = startTime;
            if (endTime) {
                result.operations[0].planEndTime = endTime;
            } else {
                result.operations[0].planEndTime = Utils.dateFormat(startTimeStamp + new Date(point.extra.planEndTime).getTime() - new Date(point.extra.planStartTime).getTime(), '-', true);
            }
        } else { // 组模式，
            let timeChange = startTimeStamp - new Date(point.extra.planStartTime).getTime(),
                singleOperation = null;
            result.operations = [];
            point.series.points.forEach(p => {
                if (p.extra.operationStat === 'S') {
                    singleOperation = OperationParser.toOperation(p);

                    singleOperation.planStartTime = Utils.dateFormat(
                        new Date(p.extra.planStartTime).getTime() + timeChange, '-', true);
                    singleOperation.planEndTime = Utils.dateFormat(
                        new Date(p.extra.planEndTime).getTime() + timeChange, '-', true);

                    result.operations.push(singleOperation);
                }
            });
        }

        return result;
    }

    /**
     * 保存数据
     * @param {Object | undefined} data 需要更新的数据，默认是从 changedOperations 里计算出来的，某些接口（例如更新计划时间）会调这个函数，所以会传 data
     * @param {fuction | undefined} callback 回调函数，针对有 data 参数的情况
     */
    saveOperationData(data, callback) {
        if (!data) {
            if (Utils.isEmpty(this.changedOperations)) {
                return false;
            } else { // 根据 changedOperations 组装数据
                data = [];

                let totalSeries = Object.keys(this.changedOperations),
                    counter = 0,
                    i = 0,
                    series = this.chart.series,
                    total = series.length,
                    operations = null,
                    j = 0,
                    points = null,
                    pointLength = 0;

                for (; i < total; i++) {
                    if (this.changedOperations[series[i].options.id]) {
                        operations = {};
                        operations.operationRoute = OperationParser.toRoute(series[i]);
                        operations.operations = [];

                        points = series[i].points;
                        pointLength = points.length;

                        for (j = 0; j < pointLength; j++) {
                            if (this.changedOperations[series[i].options.id][points[j].extra.sid]) {
                                operations.operations.push(
                                    OperationParser.toOperation(series[i].points[j])
                                )
                            }
                        }

                        data.push(operations);
                        counter++;
                        if (counter >= totalSeries) {
                            break;
                        }
                    }
                }
            }
        }

        this.showLoading();
        Http.post(Config.api.saveOperation, JSON.stringify(data), result => {
            this.cache.updateOperationsRute(result);
            if (callback) {
                callback(result);
            } else {

                // 结果处理
                console.log(result);


                this.parseOperationData(result, false, series => {
                    series.forEach(s => {
                        this.chart.get(s.id).update(s, false);
                    });
                    this.chart.redraw();
                });


                this.changedOperations = {};
                Events.emit('statusChange', 'dataUpdate', false);
                this.hideLoading();
                this.doValidate();
            }
        });
    }

    doValidate(isCCMOnly) {
        this.timer.addTimeout('doValidate', 300, () => {
            this.validate[isCCMOnly ? 'validateCCMOnly' : 'validate']();
        });
    }

    // 干扰事件
    raodongAction(){
        this.showLoading();
        Http.post(Config.api.raodong, null, res => {
            this.hideLoading()
            console.log(res)
            let dom1
            let modal = new Modal('干扰事件', body => {
                dom1 = Dom.append(body, 'div');
                dom1.style.width = '100%';
                dom1.style['max-height'] = '500px'
                dom1.style.overflow = 'auto'
                let innerHtml = '<table><thead><tr style="position: sticky;top: 0;z-index: 10;"><th>炉次制造命令</th><th>事件内容</th><th>是否已确认</th><th>焦次号</th><th>事件发生时间</th></tr></thead>';
                for(let i = 0; i <res.length ;i++){
                    innerHtml += '<tr><td>'+res[i].chargeId+'</td><td>'+res[i].rdType+'</td><td>'+(res[i].rdFlag === 1? '是': '否')+'</td><td>'+res[i].facilityNo+'</td><td>'+res[i].createdDt+'</td></tr>';
                }
                innerHtml += '</table>'
                dom1.innerHTML = innerHtml
            }, isOK => {}, {
                type: 'alert',
                className: 'modal-large'
            });
        })
    }
}

export default Gantt;
